home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / libg_261.zip / libg_261 / libio / iopopen.c < prev    next >
C/C++ Source or Header  |  1994-07-14  |  5KB  |  222 lines

  1. /* 
  2. Copyright (C) 1993 Free Software Foundation
  3.  
  4. This file is part of the GNU IO Library.  This library is free
  5. software; you can redistribute it and/or modify it under the
  6. terms of the GNU General Public License as published by the
  7. Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with GNU CC; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. As a special exception, if you link this library with files
  20. compiled with a GNU compiler to produce an executable, this does not cause
  21. the resulting executable to be covered by the GNU General Public License.
  22. This exception does not however invalidate any other reasons why
  23. the executable file might be covered by the GNU General Public License. */
  24.  
  25. /*  written by Per Bothner (bothner@cygnus.com) */
  26.  
  27. #define _POSIX_SOURCE
  28. #include "libioP.h"
  29. #if _IO_HAVE_SYS_WAIT
  30. #include <signal.h>
  31. #include <unistd.h>
  32. #ifdef __STDC__
  33. #include <stdlib.h>
  34. #endif
  35. #include <sys/wait.h>
  36.  
  37. #ifndef _IO_fork
  38. #define _IO_fork vfork /* defined in libiberty, if needed */
  39. _IO_pid_t _IO_fork();
  40. #endif
  41.  
  42. #endif /* _IO_HAVE_SYS_WAIT */
  43.  
  44. #ifndef _IO_pipe
  45. #define _IO_pipe pipe
  46. extern int _IO_pipe();
  47. #endif
  48.  
  49. #ifndef _IO_dup2
  50. #define _IO_dup2 dup2
  51. extern int _IO_dup2();
  52. #endif
  53.  
  54. #ifndef _IO_waitpid
  55. #define _IO_waitpid waitpid
  56. #endif
  57.  
  58. #ifndef _IO_execl
  59. #define _IO_execl execl
  60. #endif
  61. #ifndef _IO__exit
  62. #define _IO__exit _exit
  63. #endif
  64.  
  65. struct _IO_proc_file
  66. {
  67.   struct _IO_FILE_plus file;
  68.   /* Following fields must match those in class procbuf (procbuf.h) */
  69.   _IO_pid_t pid;
  70.   struct _IO_proc_file *next;
  71. };
  72. typedef struct _IO_proc_file _IO_proc_file;
  73.  
  74. static struct _IO_proc_file *proc_file_chain = NULL;
  75.  
  76. _IO_FILE *
  77. _IO_proc_open(fp, command, mode)
  78.      _IO_FILE* fp;
  79.      const char *command;
  80.      const char *mode;
  81. {
  82. #if _IO_HAVE_SYS_WAIT
  83.   int read_or_write;
  84.   int pipe_fds[2];
  85.   int parent_end, child_end;
  86.   _IO_pid_t child_pid;
  87.   if (_IO_file_is_open(fp))
  88.     return NULL;
  89.   if (_IO_pipe(pipe_fds) < 0)
  90.     return NULL;
  91.   if (mode[0] == 'r')
  92.     {
  93.       parent_end = pipe_fds[0];
  94.       child_end = pipe_fds[1];
  95.       read_or_write = _IO_NO_WRITES;
  96.     }
  97.   else
  98.     {
  99.       parent_end = pipe_fds[1];
  100.       child_end = pipe_fds[0];
  101.       read_or_write = _IO_NO_READS;
  102.     }
  103.   ((_IO_proc_file*)fp)->pid = child_pid = _IO_fork();
  104.   if (child_pid == 0)
  105.     {
  106.       int child_std_end = mode[0] == 'r' ? 1 : 0;
  107.       _IO_close(parent_end);
  108.       if (child_end != child_std_end)
  109.     {
  110.       _IO_dup2(child_end, child_std_end);
  111.       _IO_close(child_end);
  112.     }
  113.       /* Posix.2:  "popen() shall ensure that any streams from previous
  114.          popen() calls that remain open in the parent process are closed
  115.      in the new child process." */
  116.       while (proc_file_chain)
  117.     {
  118.       _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain));
  119.       proc_file_chain = proc_file_chain->next;
  120.     }
  121.  
  122.       _IO_execl("/bin/sh", "sh", "-c", command, NULL);
  123.       _IO__exit(127);
  124.     }
  125.   _IO_close(child_end);
  126.   if (child_pid < 0)
  127.     {
  128.       _IO_close(parent_end);
  129.       return NULL;
  130.     }
  131.   _IO_fileno(fp) = parent_end;
  132.  
  133.   /* Link into proc_file_chain. */
  134.   ((_IO_proc_file*)fp)->next = proc_file_chain;
  135.   proc_file_chain = (_IO_proc_file*)fp;
  136.  
  137.   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
  138.   return fp;
  139. #else /* !_IO_HAVE_SYS_WAIT */
  140.   return NULL;
  141. #endif
  142. }
  143.  
  144. _IO_FILE *
  145. _IO_popen(command, mode)
  146.      const char *command;
  147.      const char *mode;
  148. {
  149.   _IO_proc_file *fpx = (_IO_proc_file*)malloc(sizeof(_IO_proc_file));
  150.   _IO_FILE *fp = (_IO_FILE*)fpx;
  151.   if (fp == NULL)
  152.     return NULL;
  153.   _IO_init(fp, 0);
  154.   fp->_jumps = &_IO_proc_jumps;
  155.   _IO_file_init(fp);
  156.   ((struct _IO_FILE_plus*)fp)->vtable = NULL;
  157.   if (_IO_proc_open (fp, command, mode) != NULL)
  158.     return fp;
  159.   free (fpx);
  160.   return NULL;
  161. }
  162.  
  163. int
  164. _IO_proc_close(fp)
  165.      _IO_FILE *fp;
  166. {
  167.   /* This is not name-space clean. FIXME! */
  168. #if _IO_HAVE_SYS_WAIT
  169.   int wstatus;
  170.   _IO_proc_file **ptr = &proc_file_chain;
  171.   _IO_pid_t wait_pid;
  172.   int status = -1;
  173.   
  174.   /* Unlink from proc_file_chain. */
  175.   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
  176.     {
  177.       if (*ptr == (_IO_proc_file*)fp)
  178.     {
  179.       *ptr = (*ptr)->next;
  180.       status = 0;
  181.       break;
  182.     }
  183.     }
  184.  
  185.   if (status < 0 || _IO_close(_IO_fileno(fp)) < 0)
  186.     return -1;
  187.   /* POSIX.2 Rationale:  "Some historical implementations either block
  188.      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
  189.      for the child process to terminate.  Since this behavior is not
  190.      described in POSIX.2, such implementations are not conforming." */
  191.   do
  192.     {
  193.       wait_pid = _IO_waitpid (((_IO_proc_file*)fp)->pid, &wstatus, 0);
  194.     } while (wait_pid == -1 && errno == EINTR);
  195.   if (wait_pid == -1)
  196.     return -1;
  197.   return wstatus;
  198. #else /* !_IO_HAVE_SYS_WAIT */
  199.   return -1;
  200. #endif
  201. }
  202.  
  203. struct _IO_jump_t _IO_proc_jumps = {
  204.   _IO_file_overflow,
  205.   _IO_file_underflow,
  206.   _IO_file_xsputn,
  207.   _IO_default_xsgetn,
  208.   _IO_file_read,
  209.   _IO_file_write,
  210.   _IO_file_doallocate,
  211.   _IO_default_pbackfail,
  212.   _IO_file_setbuf,
  213.   _IO_file_sync,
  214.   _IO_file_finish,
  215.   _IO_proc_close,
  216.   _IO_file_stat,
  217.   _IO_file_seek,
  218.   _IO_file_seekoff,
  219.   _IO_default_seekpos,
  220.   _IO_default_uflow
  221. };
  222.